#ifndef _NE_ENGINE_H_
#define _NE_ENGINE_H_

#include <common/Event.h>
#include <common/Singleton.h>

#include <system/Log.h>
#include <system/Screen.h>
#include <system/Timer.h>
#include <system/Mouse.h>
#include <system/Keyboard.h>
#include <system/MouseEvent.h>
#include <system/KeyboardEvent.h>

#include <graphics/RenderSystem.h>
#include <graphics/MaterialManager.h>
#include <graphics/ImageManager.h>
#include <graphics/TextureManager.h>
#include <graphics/FontManager.h>
#include <graphics/GLBufferObjectManager.h>
#include <graphics/GLSLManager.h>
#include <graphics/MeshManager.h>
#include <graphics/SkeletonManager.h>
#include <graphics/ModelManager.h>

#include <animation/AnimationManager.h>

//#include <UI/UIManager.h>

namespace ne
{
    class NEAPI Engine : public Singleton<Engine>
    {
        public:
            Engine();

            bool initialize();

            bool isReady() const;

            void setWorkSpace(const std::string &space);
            const std::string& getWorkSpace() const { return mWorkSpace; }

            Screen* getScreen() const { return mpScreen; }
            void setResolution(const uint32_t width, const uint32_t height);
            void setFullScreen(const bool b);

            Timer* getTimer() const { return mpTimer; }

            Camera* getPerspectiveCamera() const { return mpPerspectiveCamera; }
            Viewport* getPerspectiveViewport() const { return mpPerspectiveViewport; }

            Camera* getOrthographicCamera() const { return mpOrthographicCamera; }
            Viewport* getOrthographicViewport() const { return mpOrthographicViewport; }

            RenderSystem* getRenderSystem() const { return mpRenderSystem; }

            // Managers
            GLBufferObjectManager* getBufferObjectManager() const { return mpBufferObjectManager; }
            GLSLManager* getGLSLManager() const { return mpGLSLManager; }
            ImageManager* getImageManager() const { return mpImageManager; }
            TextureManager* getTextureManager() const { return mpTextureManager; }
            MaterialManager* getMaterialManager() const { return mpMaterialManager; }
            FontManager* getFontManager() const { return mpFontManager; }
            MeshManager* getMeshManager() const { return mpMeshManager; }
            SkeletonManager* getSkeletonManager() const { return mpSkeletonManager; }
            AnimationManager* getAnimationManager() const { return mpAnimationManager; }
            ModelManager* getModelManager() const { return mpModelManager; }
            //UIManager* getUIManager() const { return mpUIManager; }

            FontPtr getFont() const { return mpFont; }

            // Mouse and Keyboard
            Mouse* getMouse() const { return mpMouse; }
            void setMousePosition(const real x, const real y);
            void setMouseButtonUp(const MouseButton &button);
            void setMouseButtonDown(const MouseButton &button);
            void setMouseWheelVariation(const real v);

            Keyboard* getKeyboard() const { return mpKeyboard; }
            void setKeyboardModifierUp(const KeyboardModifier &km);
            void setKeyboardModifierDown(const KeyboardModifier &km);
            void setKeyboardTranslationMode(const KeyboardTranslationMode &ktm);
            void setKeyboardKeyUp(const KeyboardKey &key);
            void setKeyboardKeyDown(const KeyboardKey &key);
            void setCharacter(const uint32_t character);

            virtual ~Engine();

        public:
            static Engine& GetSingleton();

            static Engine* GetSingletonPtr();

        private:
            std::string mWorkSpace;

            Screen *mpScreen;
            Timer *mpTimer;
            Mouse *mpMouse;
            Keyboard *mpKeyboard;

            Camera *mpPerspectiveCamera;
            Viewport *mpPerspectiveViewport;
            Camera *mpOrthographicCamera;
            Viewport *mpOrthographicViewport;

            RenderSystem *mpRenderSystem;

            GLBufferObjectManager *mpBufferObjectManager;
            GLSLManager *mpGLSLManager;
            ImageManager *mpImageManager;
            TextureManager *mpTextureManager;
            MaterialManager *mpMaterialManager;
            FontManager *mpFontManager;
            MeshManager *mpMeshManager;
            SkeletonManager *mpSkeletonManager;
            AnimationManager *mpAnimationManager;
            ModelManager *mpModelManager;
            //UIManager *mpUIManager;

            FontPtr mpFont;

            bool mIsReady;
    };
}

#endif
